package com.sunrise.estoque.servico;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import lombok.Getter;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sunrise.configuracoes.repositorio.iface.FilialDao;
import com.sunrise.estoque.repositorio.iface.AjusteEstoqueDao;
import com.sunrise.estoque.repositorio.iface.EstoqueAjustadoDao;
import com.sunrise.estoque.repositorio.iface.EstoqueDao;
import com.sunrise.estoque.repositorio.iface.HistoricoAjusteDao;
import com.sunrise.estoque.repositorio.iface.ProdutoDao;
import com.sunrise.generico.entidade.AjusteEstoque;
import com.sunrise.generico.entidade.Estoque;
import com.sunrise.generico.entidade.EstoqueAjustado;
import com.sunrise.generico.entidade.Filial;
import com.sunrise.generico.entidade.HistoricoAjuste;
import com.sunrise.generico.entidade.Produto;
import com.sunrise.generico.entidade.Usuario;
import com.sunrise.generico.enums.Status;
import com.sunrise.generico.visao.Filtro;

@Service
@Transactional(readOnly = true)
public class ManterAjusteEstoqueService {

	@Resource(name = "ajusteEstoqueDaoImpl")
	@Getter
	private AjusteEstoqueDao ajusteEstoqueDAO;

	@Resource(name = "produtoDaoImpl")
	@Getter
	private ProdutoDao produtoDAO;

	@Resource(name = "estoqueDaoImpl")
	@Getter
	private EstoqueDao estoqueDAO;

	@Resource(name = "estoqueAjustadoDaoImpl")
	@Getter
	private EstoqueAjustadoDao estoqueAjustadoDAO;
	
	@Resource(name = "historicoAjusteDaoImpl")
	@Getter
	private HistoricoAjusteDao historicoAjusteDAO;
	
	@Resource(name = "filialDaoImpl")
	@Getter
	private FilialDao filialDAO;

	public Collection<AjusteEstoque> buscarPorFiltros(Filtro filtro) {
		Collection<AjusteEstoque> ajustesEstoque =  getAjusteEstoqueDAO().buscarPorFiltro(filtro);
		for(AjusteEstoque ajusteEstoque : ajustesEstoque){
			ajusteEstoque.getEstoquesAjustados().size();
			ajusteEstoque.getHistoricosAjuste().size();
		}
		return ajustesEstoque;
	}

	public Collection<EstoqueAjustado> adicionarProtudosSelecionados(Produto[] produtosSelecionados, Long idFilial) {
		Collection<EstoqueAjustado> estoquesAjustados = new ArrayList<EstoqueAjustado>();
		for (Produto prod : produtosSelecionados) {
			EstoqueAjustado estoqueAjustado = new EstoqueAjustado();
			Estoque estoque = estoqueDAO.buscarPorProduto(prod.getId(), idFilial);
			if (estoque == null) {
				estoque = new Estoque();
				estoque.setProduto(prod);
				estoque.setQuantidade(new BigDecimal(0));
				estoque.setQuantidadeMaxima(new BigDecimal(0));
				estoque.setQuantidadeMinima(new BigDecimal(0));
				estoqueAjustado.setEstoque(estoque);
			} else {
				estoqueAjustado.setEstoque(estoque);
			}

			estoqueAjustado.setValorAnterior(estoqueAjustado.getEstoque().getQuantidade());
			estoqueAjustado.setValorPosterior(estoqueAjustado.getEstoque().getQuantidade());
			estoquesAjustados.add(estoqueAjustado);
		}

		return estoquesAjustados;
	}

	public List<Produto> buscarProdutosPorCodigoNome(Produto produtoFiltro) {
		return getProdutoDAO().buscarProdutosPorCodigoOuNome(produtoFiltro);
	}

	public List<Produto> buscarProdutoPorNome(String nome) {
		return getProdutoDAO().listarPorNome(nome);
	}

	@Transactional(readOnly = false)
	public void inserir(AjusteEstoque entidade) {
		for (EstoqueAjustado ea : entidade.getEstoquesAjustados()) {
			if (!ea.getEstoque().getQuantidade().equals(ea.getValorPosterior())) {
				ea.getEstoque().setQuantidade(ea.getValorPosterior());
				if (ea.getEstoque().getQuantidade().longValue() > ea.getEstoque().getQuantidadeMaxima().longValue()) {
					ea.getEstoque().setQuantidadeMaxima(ea.getValorPosterior());
				}

				if (ea.getEstoque().getQuantidade().longValue() < ea.getEstoque().getQuantidadeMinima().longValue()) {
					ea.getEstoque().setQuantidadeMaxima(ea.getValorPosterior());
				}
				if (ea.getEstoque().getId() == null) {
					getEstoqueDAO().inserir(ea.getEstoque());
				} else {
					getEstoqueDAO().alterar(ea.getEstoque());
				}
			}
			ea.setAjusteEstoque(entidade);
			getEstoqueAjustadoDAO().inserir(ea);
		}
		if(entidade.getHistoricosAjuste() == null){
			entidade.setHistoricosAjuste(new ArrayList<HistoricoAjuste>());
		}
		entidade.getHistoricosAjuste().add(criarHistorico(entidade, Status.REALIZADO));
		entidade.setStatus(Status.REALIZADO);
		entidade.setDataAjuste(new Date());
		getAjusteEstoqueDAO().inserir(entidade);
	}

	private HistoricoAjuste criarHistorico(AjusteEstoque entidade, Status status) {
		HistoricoAjuste historico = new HistoricoAjuste();
		historico.setAjusteEstoque(entidade);
		historico.setData(new Date());
		historico.setStatus(status);
		getHistoricoAjusteDAO().inserir(historico);
		return historico;
	}

	@Transactional(readOnly = false)
	public void cancelarAjuste(AjusteEstoque entidade) {
		for (EstoqueAjustado ea : entidade.getEstoquesAjustados()) {

			if (ea.getValorAnterior().compareTo(ea.getValorPosterior()) > 0) {
				BigDecimal diferenca = ea.getValorAnterior().subtract(ea.getValorPosterior());
				ea.getEstoque().setQuantidade(ea.getEstoque().getQuantidade().add(diferenca));
			} else if (ea.getValorAnterior().compareTo(ea.getValorPosterior()) < 0) {
				BigDecimal diferenca = ea.getValorPosterior().subtract(ea.getValorAnterior());
				ea.getEstoque().setQuantidade(ea.getEstoque().getQuantidade().subtract(diferenca));
			}
			getEstoqueDAO().alterar(ea.getEstoque());
		}
		if(entidade.getHistoricosAjuste() == null){
			entidade.setHistoricosAjuste(new ArrayList<HistoricoAjuste>());
		}
		entidade.getHistoricosAjuste().add(criarHistorico(entidade, Status.CANCELADO));
		entidade.setStatus(Status.CANCELADO);
		getAjusteEstoqueDAO().alterar(entidade);
	}

	public Collection<Filial> listarFiliaisPorUsuario(Usuario usuarioLogado) {
		return getFilialDAO().listarPorUsuario(usuarioLogado);
	}

}